package com.wangbo.regexp;

import org.junit.jupiter.api.Test;

import java.util.regex.Matcher;
import java.util.regex.Pattern;

/**
 * 正则匹配底层实现原理
 */
public class RegTheory {

    /**
     * matcher 方法：
     *   1. find() 原理：
     *     1) 根据指定的模式，定位满足模式的子序列(例如：Java)
     *     2) 找到后，将子序列的起始字符索引(begin)记录到 matcher 对象的属性 int[] groups 中，即 groups[0] = begin，
     *        把该子序列的末尾字符索引(end)加1后，也记录到 groups 中 ，即 groups[1] = end + 1;
     *     3) 同时更新 oldLast 的值为 end+1，即 oldLast = end + 1，下次执行 find() 时，从 end+1 开始匹配。
     *   2. group(0)，返回匹配子序列，原理：
     *     1) 根据 groups[0] 和 groups[1] 记录的位置，从 content 截取子序列返回；
     *     2) 截取遵循左闭右开原则，即 [groups[0], groups[1])，包含 groups[0] 对应字符，但是不包含 groups[1] 对应字符。
     *   3. group(n) (n > 0)，返回匹配子序列中的第 n 个分组，原理：
     *     1) 正则表达式中如果有()，每个()表示一个分组，第1个分组对应 1，第2个分组对应 2，...，第n个分组对应 n；
     *        所有分组的起始字符索引(begin)和末尾字符索引(end)+1都记录在 matcher 对象的 groups 数组中，分别对应 groups[2*n] 和 groups[2*n+1]；
     *     2) 根据 groups[2*n] 和 groups[2*n+1] 记录的位置，从 content 截取子序列返回；
     *     3) 截取遵循左闭右开原则，即 [groups[2*n], groups[2*n+1])，包含 groups[2*n] 对应字符，但是不包含 groups[2*n+1] 对应字符。
     */
    @Test
    public void test01() {
        String content = "1991abc5246ddd9984ccc";

        String regexp = "(\\d\\d)(\\d\\d)";  // 4位数字，分组
        Pattern pattern = Pattern.compile(regexp);
        Matcher matcher = pattern.matcher(content);

        int num = 0;
        while (matcher.find()) {
            System.out.printf("第%d次找到：%s%n", ++num, matcher.group(0));
            System.out.printf("第1个分组：%s%n", matcher.group(1));
            System.out.printf("第2个分组：%s%n", matcher.group(2));
        }
    }
}
